/* 
 * File:   Lista.cpp
 * Author: max
 * 
 * Created on October 6, 2012, 9:58 AM
 */

#include "Lista.h"
#include "Nodo.h"
#include <cstdlib>

using namespace std;
using namespace TP::Colecciones;

//------------------------------------------------------------------------------

Lista::Lista() {
    this->raiz = NULL;
}

//------------------------------------------------------------------------------

Lista::~Lista() {
    this->Limpiar();
}

//------------------------------------------------------------------------------

bool Lista::Vacia() {
    return this->raiz == NULL;
}

//------------------------------------------------------------------------------

void* Lista::Agregar (void* pDato){
    
    if (NULL != pDato)
    {
        if (!this->Vacia())
            this->NodoUltimo()->setSiguiente(new Nodo(pDato));
        else
            this->raiz = new Nodo(pDato);
    }
    
    return pDato;
}

//------------------------------------------------------------------------------

void* Lista::Remover (void* pDato){
    
    Nodo* nodo = this->GetNodo (pDato);
    
    if (nodo)
    {
        // Necesito el anterior. Lo busco.
        Nodo *cursor = this->raiz
           , *previo = NULL;
        
        while (cursor != nodo)
        {
            previo = cursor;
            cursor = cursor->Siguiente();
        }
        
        if (NULL != previo)
            previo->setSiguiente(nodo->Siguiente());
        else
            this->raiz = nodo->Siguiente();
        
        delete nodo;
    }
    return pDato;
}

//------------------------------------------------------------------------------

void* Lista::Primero(){
    
    void* dato = NULL;
    
    if (!this->Vacia())
        dato = this->raiz->Dato();
    
    return dato;
}

//------------------------------------------------------------------------------

void* Lista::Ultimo(){
    
    void* cursor = this->Primero();
    void* anterior = NULL;
    
    while (cursor != NULL)
    {
        anterior = cursor;
        cursor = this->Siguiente(cursor);
    }
    
    return anterior;
}

//------------------------------------------------------------------------------

void* Lista::Siguiente (void* pDato){
    
    void* dato = NULL;
    Nodo* nodo = this->GetNodo(pDato);
    
    if (nodo)
        if (NULL != nodo->Siguiente())
            dato = nodo->Siguiente()->Dato();
    
    return dato;
}

//------------------------------------------------------------------------------

void Lista::Limpiar(){

    while (!this->Vacia())
    {
        Nodo* nodo = this->raiz;
        this->raiz = nodo->Siguiente();
        delete nodo;
    }
}


long Lista::Count(){
    
    long quantity = 0;
    void* cursor = Primero();
    
    while (cursor != NULL){
         quantity++;
         cursor = Siguiente(cursor);
    }
    
    return quantity;
}

// =============================================================================

Nodo* Lista::NodoUltimo (){
    
    Nodo* nodo = NULL;
    
    if (!this->Vacia())
    {
        nodo = this->raiz;
        while (NULL != nodo->Siguiente())
            nodo = nodo->Siguiente();
    }
    
    return nodo;
}

//------------------------------------------------------------------------------

Nodo* Lista::GetNodo (void* pDato){
    
    Nodo* cursor = this->raiz;
    bool encontrado = false;
    
    while (NULL != cursor && !encontrado)
    {
        encontrado = cursor->Dato() == pDato;
        if (!encontrado)
            cursor = cursor->Siguiente();
    }
    return cursor;
}
